package com.shengqin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shengqin.common.pojo.CommonPage;
import com.shengqin.config.CommonException;
import com.shengqin.entity.*;
import com.shengqin.listeners.model.ArrangeImportModel;
import com.shengqin.mapper.PlanApplyProjectMapper;
import com.shengqin.pojo.exam.*;
import com.shengqin.pojo.plan.PlanQueryParam;
import com.shengqin.service.*;
import com.shengqin.utils.GradeUtil;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
@Slf4j
public class PlanApplyProjectServiceImpl extends ServiceImpl<PlanApplyProjectMapper, PlanApplyProject> implements IPlanApplyProjectService {

    private final static DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Resource
    private SysHealthProjectService healthProjectService;
    @Resource
    private IPlanStudentService planStudentService;
    @Resource
    private ISchoolService schoolService;
    @Resource
    private ITestResultService testResultService;
    @Resource
    private ISummaryResultService summaryResultService;

    @Resource
    private IPlanFreeTestService freeTestService;
    @Resource
    private IPlanService planService;
    @Resource
    private IUserService userService;

    @Autowired
    @Qualifier("calculateExecutor")
    private ThreadPoolExecutor calculateExecutor;

    @Override
    public Page<PlanApplyProject> queryPage(CommonPage<PlanApplyQueryParam> pageQueryParam) {
        PlanApplyQueryParam queryParam = pageQueryParam.getQueryParam();
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, queryParam.getPlanId());
        if (StringUtils.hasLength(queryParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, queryParam.getStudyCode());
        }
        if (StringUtils.hasLength(queryParam.getName())) {
            wrapper.lambda().eq(PlanApplyProject::getName, queryParam.getName());
        }
        if (StringUtils.hasLength(queryParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, queryParam.getIdNumber());
        }
        if (StringUtils.hasLength(queryParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, queryParam.getCardNo());
        }
        if (StringUtils.hasLength(queryParam.getSex())) {
            wrapper.lambda().eq(PlanApplyProject::getSex, queryParam.getSex());
        }
        if (queryParam.getGradeId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getGradeId, queryParam.getGradeId());
        }
        if (queryParam.getSchoolId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getSchoolId, queryParam.getSchoolId());
        }
        if (queryParam.getClassesId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getClassesId, queryParam.getClassesId());
        }
        if (queryParam.getGroupNo() != null) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, queryParam.getGroupNo());
        }
        Page<PlanApplyProject> page = new Page<>(pageQueryParam.getPageNo(), pageQueryParam.getPageSize());
        page(page, wrapper);
        buildRecords(page.getRecords());
        return page;
    }

    private void buildRecords(List<PlanApplyProject> records) {
        if (!CollectionUtils.isEmpty(records)) {
            records.forEach(item -> {
                item.setGradeName(GradeUtil.getGradeName(item.getGradeId()));
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSaveData(List<PlanApplyProject> cachedDataList, Integer planId) {
        try {
            Set<String> schoolNames = new HashSet<>();
            Set<String> studyCodes = new HashSet<>();
            cachedDataList.forEach(planApplyProject -> {
                studyCodes.add(planApplyProject.getStudyCode());
                if (StringUtils.hasLength(planApplyProject.getSchoolName())) {
                    if (StringUtils.hasLength(planApplyProject.getSchoolName().trim())) {
                        schoolNames.add(planApplyProject.getSchoolName().trim());
                    }
                }
            });
            Map<String, PlanApplyProject> studyApplyProjectMap;
            if (!CollectionUtils.isEmpty(studyCodes)) {
                List<PlanApplyProject> oldApplyProjects = queryByPlanIdAndStudyCodes(planId, studyCodes);
                studyApplyProjectMap = oldApplyProjects.stream().collect(Collectors.toMap(PlanApplyProject::getStudyCode, p -> p));
            } else {
                studyApplyProjectMap = new HashMap<>();
            }
            if (!CollectionUtils.isEmpty(schoolNames)) {
                List<School> schoolList = schoolService.listByNames(schoolNames);
                if (!CollectionUtils.isEmpty(schoolList)) {
                    String loginUserId = StpUtil.getLoginIdAsString();
                    User user = userService.getById(loginUserId);
                    List<School> schools = schoolService.listByUserId(user.getId());
                    List<String> schoolIds = schools.stream().map(s -> s.getId().toString()).collect(Collectors.toList());
                    Map<String, School> schoolMap = schoolList.stream().filter(s -> schoolIds.contains(s.getId().toString())).collect(Collectors.toMap(School::getName, s -> s));
                    cachedDataList.forEach(item -> {
                        PlanApplyProject oldApplyProject = studyApplyProjectMap.getOrDefault(item.getStudyCode(), null);

                        if (oldApplyProject != null) {
                            item.setId(oldApplyProject.getId());
                        }

                        item.setPlanId(planId);
                        School school = schoolMap.getOrDefault(item.getSchoolName(), null);
                        if (school != null) {
                            item.setSchoolId(school.getId());
                        } else {
                            log.error("您没有该{}学校的权限",item.getSchoolName());
                        }
                        item.setProjectNames(buildProjectNames(item));
                        item.setCreateTime(LocalDateTime.now());
                    });
                    if (!CollectionUtils.isEmpty(cachedDataList)) {
                        this.saveOrUpdateBatch(cachedDataList);
                    }
                }
            }
        } catch (Exception e) {
            log.error("导入报名报项数据处理错误", e);
            throw new CommonException(e.getMessage());
        }
    }

    @Override
    public List<PlanApplyProject> queryByPlanIdAndStudyCodes(Integer planId, Collection<String> studyCodes) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().select(PlanApplyProject::getStudyCode, PlanApplyProject::getProjectNames,PlanApplyProject::getLocked);
        wrapper.lambda().eq(PlanApplyProject::getPlanId, planId);
        wrapper.lambda().in(PlanApplyProject::getStudyCode, studyCodes);
        return list(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean arrange(ArrangeParam arrangeParam) {

        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, arrangeParam.getPlanId());
        List<PlanApplyProject> planApplyProjects = list(wrapper);
        planApplyProjects.forEach(planApplyProject -> {
            planApplyProject.setGroupInNo(null);
            planApplyProject.setGroupNo(null);
        });
        Map<Integer, List<PlanApplyProject>> schoolStudentMap = planApplyProjects.stream().collect(Collectors.groupingBy(PlanApplyProject::getSchoolId));
        schoolStudentMap.forEach((schoolId, applyProjects) -> {
            AtomicInteger groupNum = new AtomicInteger(0);
            Map<String, List<PlanApplyProject>> projectMap = applyProjects.stream().collect(Collectors.groupingBy(PlanApplyProject::getProjectNames));
            projectMap.forEach((projectName, applyProjectList) -> {
                if(arrangeParam.getClassFixGroup()!=null){
                    if (!arrangeParam.getGradeFixGroup()) {
                        Map<String, List<PlanApplyProject>> gradeApplyMap = applyProjectList.stream().collect(Collectors.groupingBy(p -> p.getGradeId().toString()));
                        gradeApplyMap.forEach((gradeKey, gradeApplyList) -> {
                            //班级不混编
                            if (!arrangeParam.getClassFixGroup()) {
                                Map<String, List<PlanApplyProject>> classesApplyMap = gradeApplyList.stream().collect(Collectors.groupingBy(p -> p.getGradeId() + "_" + p.getClassesName()));
                                classesApplyMap.forEach((classKey, classApplyList) -> {
                                    //男女不混编
                                    if (arrangeParam.getSexGroup().equalsIgnoreCase("1")) {
                                        Map<String, List<PlanApplyProject>> sexProjectMap = classApplyList.stream().collect(Collectors.groupingBy(PlanApplyProject::getSex));
                                        sexProjectMap.forEach((sex, projects) -> {
                                            arrangeGroup(projects, arrangeParam, groupNum);
                                        });
                                    } else {
                                        arrangeGroup(classApplyList, arrangeParam, groupNum);
                                    }
                                });
                            } else {
                                //男女不混编
                                if (arrangeParam.getSexGroup().equalsIgnoreCase("1")) {
                                    Map<String, List<PlanApplyProject>> sexProjectMap = gradeApplyList.stream().collect(Collectors.groupingBy(PlanApplyProject::getSex));
                                    sexProjectMap.forEach((sex, projects) -> {
                                        arrangeGroup(projects, arrangeParam, groupNum);
                                    });
                                } else {
                                    arrangeGroup(gradeApplyList, arrangeParam, groupNum);
                                }
                            }
                        });
                    } else {
                        //班级不混编
                        if (!arrangeParam.getClassFixGroup()) {
                            Map<String, List<PlanApplyProject>> classesApplyMap = applyProjectList.stream().collect(Collectors.groupingBy(p -> p.getGradeId() + "_" + p.getClassesName()));
                            classesApplyMap.forEach((classKey, classApplyList) -> {
                                //男女不混编
                                if (arrangeParam.getSexGroup().equalsIgnoreCase("1")) {
                                    Map<String, List<PlanApplyProject>> sexProjectMap = classApplyList.stream().collect(Collectors.groupingBy(PlanApplyProject::getSex));
                                    sexProjectMap.forEach((sex, projects) -> {
                                        arrangeGroup(projects, arrangeParam, groupNum);
                                    });
                                } else {
                                    arrangeGroup(classApplyList, arrangeParam, groupNum);
                                }
                            });
                        } else {
                            //男女不混编
                            if (arrangeParam.getSexGroup().equalsIgnoreCase("1")) {
                                Map<String, List<PlanApplyProject>> sexProjectMap = applyProjectList.stream().collect(Collectors.groupingBy(PlanApplyProject::getSex));
                                sexProjectMap.forEach((sex, projects) -> {
                                    arrangeGroup(projects, arrangeParam, groupNum);
                                });
                            } else {
                                arrangeGroup(applyProjectList, arrangeParam, groupNum);
                            }
                        }
                    }
                }
            });
        });

        return true;
    }

    private void arrangeGroup(List<PlanApplyProject> applyProjects, ArrangeParam arrangeParam, AtomicInteger groupNum) {

        int startIndex = 0;
        int endIndex;

        int limit = arrangeParam.getNumForGroup();
        int size = applyProjects.size();

        List<PlanApplyProject> applyProjectList = applyProjects.stream().sorted(
                Comparator.comparingInt(PlanApplyProject::getGradeId)
                        .thenComparing(PlanApplyProject::getClassesName)).collect(Collectors.toList());

        //每次截取的开始位置小于总长度，才会继续执行
        while (startIndex < size) {
            groupNum.getAndIncrement();
            //尾部的位置
            endIndex = startIndex + limit;

            //尾部位置不能超出范围，否则就取集合的长度
            endIndex = Math.min(endIndex, size);
            //截取
            List<PlanApplyProject> subList = applyProjectList.subList(startIndex, endIndex);

            for (int i = 1; i <= subList.size(); i++) {
                PlanApplyProject planApplyProject = subList.get(i - 1);
                String key = MD5.create().digestHex16(planApplyProject.getProjectNames()).toUpperCase();
                planApplyProject.setGroupNo(planApplyProject.getSchoolId() + "-" + key.substring(0,4) + "-" + groupNum.get());
                planApplyProject.setGroupInNo(i);
            }
            Flowable.just(subList).subscribeOn(Schedulers.io()).subscribe(this::updateBatchById);

            //计算下次截取的开始位置
            startIndex = endIndex;

        }
    }

    @Override
    public Page<PlanApplyProject> queryArrangePage(CommonPage<PlanApplyQueryParam> pageQueryParam) {
        PlanApplyQueryParam queryParam = pageQueryParam.getQueryParam();
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().select(PlanApplyProject::getPlanId,PlanApplyProject::getGroupNo, PlanApplyProject::getSchoolId, PlanApplyProject::getSchoolName, PlanApplyProject::getProjectNames);
        wrapper.lambda().isNotNull(PlanApplyProject::getGroupNo);
        wrapper.lambda().eq(PlanApplyProject::getPlanId, queryParam.getPlanId());
        if (StringUtils.hasLength(queryParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, queryParam.getStudyCode());
        }
        if (StringUtils.hasLength(queryParam.getName())) {
            wrapper.lambda().eq(PlanApplyProject::getName, queryParam.getName());
        }
        if (StringUtils.hasLength(queryParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, queryParam.getIdNumber());
        }
        if (StringUtils.hasLength(queryParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, queryParam.getCardNo());
        }
        if (StringUtils.hasLength(queryParam.getSex())) {
            wrapper.lambda().eq(PlanApplyProject::getSex, queryParam.getSex());
        }
        if (queryParam.getGradeId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getGradeId, queryParam.getGradeId());
        }
        if (queryParam.getSchoolId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getSchoolId, queryParam.getSchoolId());
        }
        if (queryParam.getClassesId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getClassesId, queryParam.getClassesId());
        }
        if (queryParam.getGroupNo() != null) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, queryParam.getGroupNo());
        }
        wrapper.lambda().groupBy(PlanApplyProject::getGroupNo);
        List<String> orderColumns = new ArrayList<>();
        orderColumns.add("school_id");
        orderColumns.add("CONVERT(REGEXP_REPLACE(group_no,'[^0-9]',''), SIGNED)");
        wrapper.orderByAsc(orderColumns);
        Page<PlanApplyProject> page = new Page<>(pageQueryParam.getPageNo(), pageQueryParam.getPageSize());
        page(page, wrapper);
        buildArrangeRecords(page.getRecords(), queryParam.getPlanId());
        return page;
    }

    @Override
    public List<PlanApplyProject> checkIn(CheckInParam checkInParam) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, checkInParam.getPlanId());

        if (!StringUtils.hasLength(checkInParam.getStudyCode()) && !StringUtils.hasLength(checkInParam.getGroupNo())
                && !StringUtils.hasLength(checkInParam.getIdNumber()) && !StringUtils.hasLength(checkInParam.getCardNo())) {
            throw new CommonException("请输入查询条件进行检录");
        }

        if (StringUtils.hasLength(checkInParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, checkInParam.getStudyCode());
        }
        if (StringUtils.hasLength(checkInParam.getGroupNo())) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, checkInParam.getGroupNo());
        }
        if (StringUtils.hasLength(checkInParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, checkInParam.getIdNumber());
        }
        if (StringUtils.hasLength(checkInParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, checkInParam.getCardNo());
        }
        List<PlanApplyProject> planApplyProjects = list(wrapper);
        Set<String> studyCodes = new HashSet<>();
        planApplyProjects.forEach(planApplyProject -> {
            studyCodes.add(planApplyProject.getStudyCode());
            planApplyProject.setGradeName(GradeUtil.getGradeName(planApplyProject.getGradeId()));
            if (StringUtils.hasLength(planApplyProject.getProjectNames())) {
                List<String> projectNames = Arrays.stream(planApplyProject.getProjectNames().split(",")).sorted(Comparator.comparing(String::trim).reversed()).collect(Collectors.toList());
                planApplyProject.setProjectNameList(projectNames);
            }
            if (checkInParam.getAutoCheckIn() != null && checkInParam.getAutoCheckIn()) {
                planApplyProject.setRecordTime(LocalDateTime.now());
                planApplyProject.setRecorded(true);
            }
        });
        if (CollectionUtils.isEmpty(studyCodes)) {
            throw new CommonException("未查询到相关数据");
        }
        List<PlanFreeTest> freeTestList = freeTestService.queryByPlanIdAndStudyCodes(checkInParam.getPlanId(), studyCodes);
        Map<String, List<PlanFreeTest>> freeTestMap = freeTestList.stream().collect(Collectors.groupingBy(PlanFreeTest::getStudyCode));
        List<PlanStudent> planStudents = planStudentService.queryByPlanIdAndStudyCodes(checkInParam.getPlanId(), studyCodes);
        Map<String, PlanStudent> planStudentMap = planStudents.stream().collect(Collectors.toMap(PlanStudent::getStudyCode, p -> p));
        planApplyProjects.forEach(planApplyProject -> {
            PlanStudent planStudent = planStudentMap.getOrDefault(planApplyProject.getStudyCode(), null);
            if (planStudent != null) {
                planApplyProject.setAvatarUrl(planStudent.getAvatarUrl());
            }
            List<PlanFreeTest> planFreeTests = freeTestMap.getOrDefault(planApplyProject.getStudyCode(), null);
            List<Map<String, Object>> projectStatusList = new ArrayList<>();
            Map<String, Object> projectStatusMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(planApplyProject.getProjectNameList())) {
                Set<String> freeTestPrjNames = new HashSet<>();
                if (!CollectionUtils.isEmpty(planFreeTests)) {
                    freeTestPrjNames = planFreeTests.stream().map(PlanFreeTest::getProjectName).collect(Collectors.toSet());
                    planApplyProject.getProjectNameList().addAll(freeTestPrjNames.stream().filter(item -> !planApplyProject.getProjectNameList().contains(item)).collect(Collectors.toList()));
                }
                Set<String> finalFreeTestPrjNames = freeTestPrjNames;
                planApplyProject.getProjectNameList().forEach(projectName -> {
                    if (!CollectionUtils.isEmpty(finalFreeTestPrjNames)) {
                        if (finalFreeTestPrjNames.contains(projectName)) {
                            planFreeTests.forEach(freeTest -> {
                                if (projectName.equals(freeTest.getProjectName())) {
                                    projectStatusMap.put(projectName, freeTest.getReason());
                                }
                            });
                        } else {
                            projectStatusMap.put(projectName, "正常");
                        }
                    } else {
                        projectStatusMap.put(projectName, "正常");
                    }
                });
                projectStatusList.add(projectStatusMap);
                planApplyProject.setProjectStatusList(projectStatusList);
            }
        });
        updateBatchById(planApplyProjects);
        return planApplyProjects;
    }

    @Override
    public Map<String, Long> queryCheckInCount(CheckInParam checkInParam) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, checkInParam.getPlanId());
        wrapper.lambda().select(PlanApplyProject::getStudyCode, PlanApplyProject::getRecorded,PlanApplyProject::getRecordTime);
        List<PlanApplyProject> list = list(wrapper);
        AtomicLong recordedCount = new AtomicLong();
        AtomicLong todayRecordedCount = new AtomicLong();
        list.forEach(item -> {
            if (item.getRecorded() != null && item.getRecorded()) {
                recordedCount.getAndIncrement();
                if(item.getRecordTime() !=null){
                    if (item.getRecordTime().format(DATE_FORMAT).equals(LocalDateTime.now().format(DATE_FORMAT))) {
                        todayRecordedCount.getAndIncrement();
                    }
                }
            }
        });

        Map<String, Long> countMap = new ConcurrentHashMap<>();
        countMap.put("totalCount", (long) list.size());
        countMap.put("recordedCount", recordedCount.get());
        countMap.put("unRecordCount", list.size() - recordedCount.get());
        countMap.put("todayRecordCount", todayRecordedCount.get());
        return countMap;
    }

    @Override
    public Boolean cancelCheck(CheckInParam checkInParam) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, checkInParam.getPlanId());
        if (StringUtils.hasLength(checkInParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, checkInParam.getStudyCode());
        }
        if (StringUtils.hasLength(checkInParam.getGroupNo())) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, checkInParam.getGroupNo());
        }
        if (StringUtils.hasLength(checkInParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, checkInParam.getIdNumber());
        }
        if (StringUtils.hasLength(checkInParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, checkInParam.getCardNo());
        }
        List<PlanApplyProject> planApplyProjects = list(wrapper);
        planApplyProjects.forEach(planApplyProject -> {
            planApplyProject.setRecorded(false);
            planApplyProject.setRecordTime(null);
        });
        return updateBatchById(planApplyProjects);
    }

    @Override
    public List<PlanApplyProject> queryCheckInGroup(CheckInParam checkInParam) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, checkInParam.getPlanId());
        if (!StringUtils.hasLength(checkInParam.getGroupNo()) && checkInParam.getSchoolId() == null) {
            throw new CommonException("请输入查询条件进行检录");
        }
        if (checkInParam.getSchoolId() != null && !StringUtils.hasLength(checkInParam.getGroupNo())) {
            throw new CommonException("请输入分组号进行检录");
        }
        if (StringUtils.hasLength(checkInParam.getGroupNo())) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, checkInParam.getGroupNo());
        }
        List<PlanApplyProject> projects = list(wrapper);
        buildRecords(projects);
        if (checkInParam.getAutoCheckIn() != null && checkInParam.getAutoCheckIn()) {
            projects.forEach(planApplyProject -> {
                planApplyProject.setRecordTime(LocalDateTime.now());
                planApplyProject.setRecorded(true);
            });
            updateBatchById(projects);
        }
        return projects;
    }

    @Override
    public List<PlanApplyProject> checkInGroup(CheckInParam checkInParam) {
        List<PlanApplyProject> checkInList = queryCheckInGroup(checkInParam);
        checkInList.forEach(planApplyProject -> {
            planApplyProject.setRecordTime(LocalDateTime.now());
            planApplyProject.setRecorded(true);
        });
        if (!CollectionUtils.isEmpty(checkInList)) {
            updateBatchById(checkInList);
        }
        return checkInList;
    }

    @Override
    public List<PlanApplyProject> cancelCheckGroup(CheckInParam checkInParam) {
        List<PlanApplyProject> checkInList = queryCheckInGroup(checkInParam);
        checkInList.forEach(planApplyProject -> {
            planApplyProject.setRecordTime(null);
            planApplyProject.setRecorded(false);
        });
        if (!CollectionUtils.isEmpty(checkInList)) {
            updateBatchById(checkInList);
        }
        return checkInList;
    }

    @Override
    public Page<PlanApplyProject> queryTestProjectResult(CommonPage<PublicityQueryParam> queryPageParam) {
        PublicityQueryParam queryParam = queryPageParam.getQueryParam();

        Plan plan = planService.getById(queryParam.getPlanId());

        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, queryParam.getPlanId());

        if (!StringUtils.hasLength(queryParam.getStudyCode()) && !StringUtils.hasLength(queryParam.getGroupNo())
                && !StringUtils.hasLength(queryParam.getIdNumber()) && !StringUtils.hasLength(queryParam.getCardNo())) {
            throw new CommonException("请输入查询条件");
        }

        if (StringUtils.hasLength(queryParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, queryParam.getStudyCode());
        }
        if (StringUtils.hasLength(queryParam.getGroupNo())) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, queryParam.getGroupNo());
        }
        if (StringUtils.hasLength(queryParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, queryParam.getIdNumber());
        }
        if (StringUtils.hasLength(queryParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, queryParam.getCardNo());
        }

        Page<PlanApplyProject> page = new Page<>(queryPageParam.getPageNo(), queryPageParam.getPageSize());
        page(page, wrapper);

        Set<String> studyCodes = page.getRecords().stream().map(PlanApplyProject::getStudyCode).collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(studyCodes)) {
            throw new CommonException("未查询到相关数据");
        }
        PlanQueryParam planQueryParam = new PlanQueryParam();
        planQueryParam.setPlanId(queryParam.getPlanId());
        planQueryParam.setStudyCodes(new ArrayList<>(studyCodes));
        List<SummaryResult> summaryResultList = summaryResultService.listByPlanId(planQueryParam);
        Map<String, List<SummaryResult>> studySummaryResultMap = summaryResultList.stream().collect(Collectors.groupingBy(SummaryResult::getStudyCode));
        List<TestResult> testResults = testResultService.listByPlanIdAndStudyCodes(queryParam.getPlanId(), studyCodes);

        testResults.forEach(testResult -> {
            if(StringUtils.hasLength(testResult.getResultType()) && testResult.getResult() == null){
                testResult.setResult(testResult.getResultType());
                testResult.setExtraScore(BigDecimal.ZERO);
            }
        });

        Map<String, List<TestResult>> studyResultMap = testResults.stream().collect(Collectors.groupingBy(TestResult::getStudyCode));

        List<PlanStudent> planStudents = planStudentService.queryByPlanIdAndStudyCodes(queryParam.getPlanId(), studyCodes);
        Map<String, PlanStudent> planStudentMap = planStudents.stream().collect(Collectors.toMap(PlanStudent::getStudyCode, p -> p));

        page.getRecords().forEach(ap -> {
            PlanStudent planStudent = planStudentMap.getOrDefault(ap.getStudyCode(), null);
            if (planStudent != null) {
                ap.setAvatarUrl(planStudent.getAvatarUrl());
            }
            ap.setGradeName(GradeUtil.getGradeName(ap.getGradeId()));
            List<TestResult> stdResultList = studyResultMap.getOrDefault(ap.getStudyCode(), null);
            List<SummaryResult> studySummaryResults = studySummaryResultMap.getOrDefault(ap.getStudyCode(), null);
            if (StringUtils.hasLength(ap.getProjectNames())) {
                List<TestResult> finalResultList = new ArrayList<>();
                ap.setProjectNameList(Arrays.asList(ap.getProjectNames().split(",")));
                Map<String, List<TestResult>> finalResultMap;
                if (!CollectionUtils.isEmpty(stdResultList)) {
                    finalResultMap = stdResultList.stream().collect(Collectors.groupingBy(TestResult::getPrjName));
                    if (!CollectionUtils.isEmpty(studySummaryResults)) {
                        ap.setSummaryResult(studySummaryResults.get(0));
                    }
                } else {
                    finalResultMap = new HashMap<>();
                    SummaryResult summaryResult = new SummaryResult();
                    summaryResult.setTotalScore(BigDecimal.ZERO);
                    ap.setSummaryResult(summaryResult);
                }
                ap.getProjectNameList().forEach(projectName -> {
                    String prjName = projectName;
                    if(projectName.equals("身高体重")){
                        List<TestResult> prjResults = finalResultMap.getOrDefault(prjName, null);
                        if(CollectionUtils.isEmpty(prjResults)){
                            prjName = "BMI";
                        }
                    }
                    List<TestResult> prjResults = finalResultMap.getOrDefault(prjName, null);
                    if (!CollectionUtils.isEmpty(prjResults)) {
                        if(StringUtils.hasLength(plan.getCameraIp())){
                            String webRtcIp = plan.getCameraIp().replaceAll("https","webrtcs");
                            String webRtcUrl = webRtcIp + ":443?username=123&password=e10adc3949ba59abbe56e057f20f883e&cameraID=" + prjResults.get(0).getCameraId();
                            prjResults.get(0).setVideoUrl(webRtcUrl);
                        }
                        finalResultList.add(prjResults.get(0));
                    } else {
                        TestResult testResult = new TestResult();
                        testResult.setPrjName(projectName);
                        testResult.setResult("—");
                        testResult.setScore(BigDecimal.ZERO);
                        testResult.setFinalScore(BigDecimal.ZERO);
                        testResult.setLevel("—");
                        finalResultList.add(testResult);
                    }
                });
                ap.setTestResultList(finalResultList);
            }
        });

        return page;
    }

    @Override
    public List<PlanApplyProject> exportArrangePage(CommonPage<PlanApplyQueryParam> pageQueryParam) {
        PlanApplyQueryParam queryParam = pageQueryParam.getQueryParam();
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().select(PlanApplyProject::getPlanId,PlanApplyProject::getGroupNo, PlanApplyProject::getSchoolId, PlanApplyProject::getSchoolName, PlanApplyProject::getProjectNames);
        wrapper.lambda().isNotNull(PlanApplyProject::getGroupNo);
        wrapper.lambda().eq(PlanApplyProject::getPlanId, queryParam.getPlanId());
        if (StringUtils.hasLength(queryParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, queryParam.getStudyCode());
        }
        if (StringUtils.hasLength(queryParam.getName())) {
            wrapper.lambda().eq(PlanApplyProject::getName, queryParam.getName());
        }
        if (StringUtils.hasLength(queryParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, queryParam.getIdNumber());
        }
        if (StringUtils.hasLength(queryParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, queryParam.getCardNo());
        }
        if (StringUtils.hasLength(queryParam.getSex())) {
            wrapper.lambda().eq(PlanApplyProject::getSex, queryParam.getSex());
        }
        if (queryParam.getGradeId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getGradeId, queryParam.getGradeId());
        }
        if (queryParam.getSchoolId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getSchoolId, queryParam.getSchoolId());
        }
        if (queryParam.getClassesId() != null) {
            wrapper.lambda().eq(PlanApplyProject::getClassesId, queryParam.getClassesId());
        }
        if (queryParam.getGroupNo() != null) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, queryParam.getGroupNo());
        }
        wrapper.lambda().groupBy(PlanApplyProject::getGroupNo);
        wrapper.lambda().orderByAsc(PlanApplyProject::getGroupNo);
        List<PlanApplyProject> list = list(wrapper);
        buildArrangeRecords(list, queryParam.getPlanId());
        return list;
    }

    @Override
    public List<PlanApplyProject> queryTestProjectResultList(CommonPage<PublicityQueryParam> queryPageParam) {
        PublicityQueryParam queryParam = queryPageParam.getQueryParam();
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, queryParam.getPlanId());

        if (!StringUtils.hasLength(queryParam.getGroupNo()) && CollectionUtils.isEmpty(queryParam.getStudyCodeList())) {
            throw new CommonException("请输入查询条件");
        }

        if (StringUtils.hasLength(queryParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, queryParam.getStudyCode());
        }
        if (!CollectionUtils.isEmpty(queryParam.getStudyCodeList())) {
            wrapper.lambda().in(PlanApplyProject::getStudyCode, queryParam.getStudyCodeList());
        }
        if (StringUtils.hasLength(queryParam.getGroupNo())) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, queryParam.getGroupNo());
        }
        if (StringUtils.hasLength(queryParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, queryParam.getIdNumber());
        }
        if (StringUtils.hasLength(queryParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, queryParam.getCardNo());
        }

        List<PlanApplyProject> applyProjectList = list(wrapper);

        Set<String> studyCodes = applyProjectList.stream().map(PlanApplyProject::getStudyCode).collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(studyCodes)) {
            throw new CommonException("未查询到相关数据");
        }
        PlanQueryParam planQueryParam = new PlanQueryParam();
        planQueryParam.setPlanId(queryParam.getPlanId());
        planQueryParam.setStudyCodes(new ArrayList<>(studyCodes));
        List<SummaryResult> summaryResultList = summaryResultService.listByPlanId(planQueryParam);
        Map<String, List<SummaryResult>> studySummaryResultMap = summaryResultList.stream().collect(Collectors.groupingBy(SummaryResult::getStudyCode));
        List<TestResult> testResults = testResultService.listByPlanIdAndStudyCodes(queryParam.getPlanId(), studyCodes);
        Map<String, List<TestResult>> studyResultMap = testResults.stream().collect(Collectors.groupingBy(TestResult::getStudyCode));

        List<PlanStudent> planStudents = planStudentService.queryByPlanIdAndStudyCodes(queryParam.getPlanId(), studyCodes);
        Map<String, PlanStudent> planStudentMap = planStudents.stream().collect(Collectors.toMap(PlanStudent::getStudyCode, p -> p));

        applyProjectList.forEach(ap -> {
            PlanStudent planStudent = planStudentMap.getOrDefault(ap.getStudyCode(), null);
            if (planStudent != null) {
                ap.setAvatarUrl(planStudent.getAvatarUrl());
            }
            ap.setGradeName(GradeUtil.getGradeName(ap.getGradeId()));
            List<TestResult> stdResultList = studyResultMap.getOrDefault(ap.getStudyCode(), null);
            List<SummaryResult> studySummaryResults = studySummaryResultMap.getOrDefault(ap.getStudyCode(), null);
            if (StringUtils.hasLength(ap.getProjectNames())) {
                List<TestResult> finalResultList = new ArrayList<>();
                ap.setProjectNameList(Arrays.asList(ap.getProjectNames().split(",")));
                Map<String, List<TestResult>> finalResultMap;
                if (!CollectionUtils.isEmpty(stdResultList)) {
                    finalResultMap = stdResultList.stream().collect(Collectors.groupingBy(TestResult::getPrjName));
                    if (!CollectionUtils.isEmpty(studySummaryResults)) {
                        ap.setSummaryResult(studySummaryResults.get(0));
                    }
                } else {
                    finalResultMap = new HashMap<>();
                    SummaryResult summaryResult = new SummaryResult();
                    summaryResult.setTotalScore(BigDecimal.ZERO);
                    ap.setSummaryResult(summaryResult);
                }
                ap.getProjectNameList().forEach(projectName -> {
                    String prjName = projectName;
                    if(prjName.equalsIgnoreCase("身高体重")){
                        List<TestResult> whResults = finalResultMap.getOrDefault(prjName, null);
                        if(CollectionUtils.isEmpty(whResults)){
                            prjName = "BMI";
                        }
                    }
                    List<TestResult> prjResults = finalResultMap.getOrDefault(prjName, null);
                    if (!CollectionUtils.isEmpty(prjResults)) {
                        finalResultList.add(prjResults.get(0));
                    } else {
                        TestResult testResult = new TestResult();
                        testResult.setPrjName(projectName);
                        testResult.setResult("—");
                        testResult.setScore(BigDecimal.ZERO);
                        testResult.setFinalScore(BigDecimal.ZERO);
                        testResult.setLevel("—");
                        finalResultList.add(testResult);
                    }
                });
                ap.setTestResultList(finalResultList);
            }
        });

        buildArrangeRecords(applyProjectList, planQueryParam.getPlanId());

        return applyProjectList;
    }

    @Override
    public Boolean clearApply(PlanApplyQueryParam queryParam) {
        if (queryParam.getPlanId() == null) {
            throw new CommonException("请选择计划进行清空");
        }

        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, queryParam.getPlanId());

        return remove(wrapper);
    }

    @Override
    public Boolean lockResult(PublicityQueryParam queryParam) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, queryParam.getPlanId());

        if (!StringUtils.hasLength(queryParam.getGroupNo())) {
            throw new CommonException("请输入查询条件");
        }

        if (StringUtils.hasLength(queryParam.getStudyCode())) {
            wrapper.lambda().eq(PlanApplyProject::getStudyCode, queryParam.getStudyCode());
        }
        if (StringUtils.hasLength(queryParam.getGroupNo())) {
            wrapper.lambda().eq(PlanApplyProject::getGroupNo, queryParam.getGroupNo());
        }
        if (StringUtils.hasLength(queryParam.getIdNumber())) {
            wrapper.lambda().eq(PlanApplyProject::getIdNumber, queryParam.getIdNumber());
        }
        if (StringUtils.hasLength(queryParam.getCardNo())) {
            wrapper.lambda().eq(PlanApplyProject::getCardNo, queryParam.getCardNo());
        }

        List<PlanApplyProject> applyProjectList = list(wrapper);
        applyProjectList.forEach(project -> project.setLocked(true));
        return updateBatchById(applyProjectList);
    }

    @Override
    public void importArrange(List<ArrangeImportModel> cachedDataList, Integer planId) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, planId);
        List<PlanApplyProject> planApplyProjects = list(wrapper);
        Map<String,PlanApplyProject> applyProjectMap = planApplyProjects.stream().collect(Collectors.toMap(PlanApplyProject::getStudyCode,s -> s));

        List<PlanApplyProject> updateApplyProjects = new ArrayList<>();
        cachedDataList.forEach(item -> {
            PlanApplyProject stdApplyProject = applyProjectMap.getOrDefault(item.getStudyCode(),null);
            if (stdApplyProject != null) {
//                String key = MD5.create().digestHex16(stdApplyProject.getProjectNames()).toUpperCase();
                stdApplyProject.setGroupNo(stdApplyProject.getSchoolId() + "-" + item.getGroupNo());
                stdApplyProject.setGroupInNo(item.getGroupInNo());
                updateApplyProjects.add(stdApplyProject);
            }
        });

        Flowable.just(updateApplyProjects).subscribeOn(Schedulers.io()).subscribe(this::updateBatchById);
    }

    @Override
    public Boolean updateProjectNames(PlanApplyProject planApplyProject) {
        return updateById(planApplyProject);
    }

    @Override
    public void updateStudentInfo(Integer planId) {
        this.baseMapper.updateStudentInfo(planId);
    }

    @Override
    public List<PlanApplyProject> listByPlanId(Integer planId) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, planId);
        return list(wrapper);
    }

    @Override
    public PlanApplyProject queryByPlanIdAndStudyCode(Integer planId, String studyCode) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, planId);
        wrapper.lambda().eq(PlanApplyProject::getStudyCode, studyCode);
        return getOne(wrapper);
    }

    private void buildArrangeRecords(List<PlanApplyProject> records, Integer planId) {
        if (!CollectionUtils.isEmpty(records)) {
            Set<String> groupIds = new HashSet<>();
            records.forEach(item -> {
                groupIds.add(item.getGroupNo());
            });
            List<PlanApplyProject> projects = listByGroupNos(planId, groupIds);
            projects.forEach(planApplyProject -> {
                planApplyProject.setGradeName(GradeUtil.getGradeName(planApplyProject.getGradeId()));
                if (StringUtils.hasLength(planApplyProject.getProjectNames())) {
                    planApplyProject.setProjectNameList(Arrays.asList(planApplyProject.getProjectNames().split(",")));
                }
            });
            Map<String, List<PlanApplyProject>> testStudentMap = projects.stream().collect(Collectors.groupingBy(item -> item.getSchoolId() + "_" + item.getGroupNo()));
            records.forEach(rec -> {
                if(rec.getGroupNo().contains("-")){
                    String[] nos = rec.getGroupNo().split("-");
                    if (nos.length >=3) {
                        rec.setGroupSchoolNo(nos[2]);
                    } else {
                        rec.setGroupSchoolNo(nos[1]);
                    }
                } else {
                    rec.setGroupSchoolNo(rec.getGroupNo());
                }
                List<PlanApplyProject> list = testStudentMap.getOrDefault(rec.getSchoolId() + "_" + rec.getGroupNo(), null);
                rec.setTestStudents(CollectionUtils.isEmpty(list) ? new ArrayList<>() : list);
                Map<String,Object> maxProjectMap = buildGroupMaxProjectSize(list);
                rec.setProjectMaxSize((long)maxProjectMap.get("maxSize"));
                rec.setMaxProjectNames((List)maxProjectMap.get("maxProjectNames"));
            });
        }
    }

    private Map<String,Object> buildGroupMaxProjectSize(List<PlanApplyProject> planApplyProjects) {
        Map<String,Object> maxProjectMap = new HashMap<>();
        AtomicLong projectMaxSize = new AtomicLong(0);
        AtomicReference<List<String>> projectNameList = new AtomicReference<>(new ArrayList<>());
        planApplyProjects.forEach(item -> {
            if(StringUtils.hasLength(item.getProjectNames())){
                String[] projectNames = item.getProjectNames().split(",");
                if(projectNames.length > projectMaxSize.get()){
                    projectMaxSize.set(projectNames.length);
                    projectNameList.get().addAll(Arrays.asList(projectNames));
                }
            }
        });
        maxProjectMap.put("maxSize",projectMaxSize.get());
        maxProjectMap.put("maxProjectNames",projectNameList.get());
        return maxProjectMap;
    }

    private List<PlanApplyProject> listByGroupNos(Integer planId, Set<String> groupIds) {
        QueryWrapper<PlanApplyProject> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanApplyProject::getPlanId, planId);
        wrapper.lambda().in(PlanApplyProject::getGroupNo, groupIds);
        wrapper.lambda().orderByAsc(PlanApplyProject::getGroupInNo);
        return list(wrapper);
    }


    private String buildProjectNames(PlanApplyProject planApplyProject) {
        Set<ApplyProjectModel> models = new HashSet<>();
        if (StringUtils.hasLength(planApplyProject.getProjectName1())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName1().trim());
            applyProjectModel.setSortId(1);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName2())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName2().trim());
            applyProjectModel.setSortId(2);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName3())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName3().trim());
            applyProjectModel.setSortId(3);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName4())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName4().trim());
            applyProjectModel.setSortId(4);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName5())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName5().trim());
            applyProjectModel.setSortId(5);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName6())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName6().trim());
            applyProjectModel.setSortId(6);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName7())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName7().trim());
            applyProjectModel.setSortId(7);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName8())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName8().trim());
            applyProjectModel.setSortId(8);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName9())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName9().trim());
            applyProjectModel.setSortId(9);
            models.add(applyProjectModel);
        }
        if (StringUtils.hasLength(planApplyProject.getProjectName10())) {
            ApplyProjectModel applyProjectModel = new ApplyProjectModel();
            applyProjectModel.setName(planApplyProject.getProjectName10().trim());
            applyProjectModel.setSortId(10);
            models.add(applyProjectModel);
        }
        List<ApplyProjectModel> applyProjectModels = models.stream().sorted(Comparator.comparingInt(ApplyProjectModel::getSortId)).collect(Collectors.toList());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < applyProjectModels.size(); i++) {
            sb.append(applyProjectModels.get(i).getName());
            if (i < applyProjectModels.size() - 1) {
                sb.append(",");
            }
        }
        return sb.toString();
    }
}
